import struct


class MsgHeader:
    def __init__(self):
        self.usLen = 0
        self.sType = 0
        self.nServerId = 0
        self.nVerCode = 0
        self.nParam = 0

        self.offset = 0
    
    def writeBinary(self):
        data = struct.pack(
                    '<iHiii',  # 假设的格式字符串
                    self.usLen,
                    self.sType,
                    self.nServerId,
                    self.nVerCode,
                    self.nParam
                )
        return data
    
    def writeInt64(self, value):
        # 解析为整数，处理可能的空值情况
        if isinstance(value, str):
            parts = value.split("_")
        else:
            parts = [0, 0]
        f_value = int(parts[0]) if len(parts) > 0 and parts[0] else 0
        l_value = int(parts[1]) if len(parts) > 1 and parts[1] else 0

        data = struct.pack(
                    '<ii',  # 假设的格式字符串
                    f_value,
                    l_value
                )
        return data

    def write_utf_bytes(self, value: str, strlen: int = 0) -> bytes:
        """
        将字符串转换为UTF-8字节流，类似于ActionScript的writeUTFBytes方法
        
        参数:
            value: 要转换的字符串
            strlen: 指定的总长度，不足则用0填充
        
        返回:
            二进制字节流，可以直接与其他bytes对象相加
        """
        # 初始化字节流
        result = b''
        
        # 处理每个字符
        for c in value:
            # 获取字符的Unicode码点
            code_point = ord(c)
            
            if code_point <= 0x7F:
                # 单字节UTF-8编码
                result += struct.pack('B', code_point)
            elif code_point <= 0x7FF:
                # 双字节UTF-8编码
                byte1 = 0xC0 | (code_point >> 6)
                byte2 = 0x80 | (code_point & 0x3F)
                result += struct.pack('BB', byte1, byte2)
            elif code_point <= 0xFFFF:
                # 三字节UTF-8编码
                byte1 = 0xE0 | (code_point >> 12)
                byte2 = 0x80 | ((code_point >> 6) & 0x3F)
                byte3 = 0x80 | (code_point & 0x3F)
                result += struct.pack('BBB', byte1, byte2, byte3)
            else:
                # 四字节UTF-8编码
                byte1 = 0xF0 | (code_point >> 18)
                byte2 = 0x80 | ((code_point >> 12) & 0x3F)
                byte3 = 0x80 | ((code_point >> 6) & 0x3F)
                byte4 = 0x80 | (code_point & 0x3F)
                result += struct.pack('BBBB', byte1, byte2, byte3, byte4)
        
        # 如果指定了长度，不足则用0填充
        if strlen > 0:
            current_len = len(result)
            if current_len < strlen:
                result += struct.pack(f'{strlen - current_len}B', *([0] * (strlen - current_len)))
        
        return result

    def readBinary(self, data: bytes):
        self.usLen = self.redBase(data, "<i")
        self.sType = self.redBase(data, "<h")
        self.nServerId = self.redBase(data, "<i")
        self.nVerCode = self.redBase(data, "<i")
        self.nParam = self.redBase(data, "<i")
        
        return data
    
    def readInt64(self, data: bytes):
        fInt = self.redBase(data, "<i")
        lInt = self.redBase(data, "<i")
        
        return f"{fInt}_{lInt}"
    
    def redBase(self, data: bytes, format: str):
        header_size = struct.calcsize(format) 
        msg = struct.unpack(format, data[self.offset:self.offset+header_size])[0] # 消息
        self.offset += header_size
        return msg
    
    def read_utf_bytes(self, data, length=-1):
        """
        从二进制数据中读取UTF-8编码的字符串
        
        参数:
            data: 二进制数据(bytes类型)
            length: 要读取的字节数，-1表示读取到数据末尾
        
        返回:
            解码后的字符串
        """
        value = []
        max_pos = self.offset + length if length != -1 else len(data)
        
        while self.offset < max_pos and self.offset < len(data):
            # 读取一个字节
            c = struct.unpack('B', data[self.offset:self.offset+1])[0]
            self.offset += 1
            
            if c < 0x80:  # 单字节字符
                if c != 0:  # 跳过空字符
                    value.append(chr(c))
            elif c < 0xE0:  # 双字节字符
                if self.offset >= max_pos:
                    break
                c2 = struct.unpack('B', data[self.offset:self.offset+1])[0]
                self.offset += 1
                value.append(chr(((c & 0x3F) << 6) | (c2 & 0x7F)))
            elif c < 0xF0:  # 三字节字符
                if self.offset + 1 >= max_pos:
                    break
                c2 = struct.unpack('B', data[self.offset:self.offset+1])[0]
                self.offset += 1
                c3 = struct.unpack('B', data[self.offset:self.offset+1])[0]
                self.offset += 1
                value.append(chr(((c & 0x1F) << 12) | ((c2 & 0x7F) << 6) | (c3 & 0x7F)))
            else:  # 四字节字符
                if self.offset + 2 >= max_pos:
                    break
                c2 = struct.unpack('B', data[self.offset:self.offset+1])[0]
                self.offset += 1
                c3 = struct.unpack('B', data[self.offset:self.offset+1])[0]
                self.offset += 1
                c4 = struct.unpack('B', data[self.offset:self.offset+1])[0]
                self.offset += 1
                # 计算四字节UTF-8对应的Unicode码点
                code_point = ((c & 0x0F) << 18) | ((c2 & 0x7F) << 12) | ((c3 & 0x7F) << 6) | (c4 & 0x7F)
                value.append(chr(code_point))
        
        return ''.join(value)
    
    def sleep(self):
        print(f"{self.name} 正在睡觉")

class SendLoginAccount(MsgHeader):
    def __init__(self):
        self.GateSocket = "0_0"#int64
        self.Int64Ex = "0_0"#int64
        self.accoutSessionKey = ""#32长度
        self.worldServerId = 0
        self.ParamType = 0
        self.ParamInt64 = "0_0"#int64
        self.ParamString = ""#128长度
        super().__init__()
    
    def writeBinary(self):
        data = super().writeBinary()
        data += super().writeInt64(self.GateSocket)
        data += super().writeInt64(self.Int64Ex)
        data += super().write_utf_bytes(self.accoutSessionKey, 32)
        data += struct.pack('<i', self.worldServerId)
        data += struct.pack('<i', self.ParamType)
        data += super().writeInt64(self.ParamInt64)
        data += super().write_utf_bytes(self.ParamString, 128)
        return data

# 角色列表
class MsgAccountRole(MsgHeader):
    def __init__(self):
        self.count = 0
        self.IsNewCreate = 0
        self.arrRoles = []
        self.IsServerDebug = 0

        super().__init__()
    
    def readBinary(self, data: bytes):
        super().readBinary(data)
        self.IsNewCreate = self.redBase(data, "<i")
        self.count = self.redBase(data, "<i")
        self.IsServerDebug = self.redBase(data, "<b")

        for i in range(self.count):
            role = NetChar()
            role.offset = self.offset
            role.readBinary(data)
            self.arrRoles.append(role)
            self.offset = role.offset

        return data

class NetChar(MsgHeader):
    def __init__(self):
        self.RoleIndex = "0_0"
        self.mName = ""
        self.mLevel = 0
        self.mJob = 0
        self.mGender = 0
        self.mOnline = 0
        self.mRid = 0
        self.bSelected = 0
        self.bDeleted = 0
        self.bJinYong = 0
        self.RoleIndexString = "null"
        self.createTime = 0
        self.mAge = 0
        self.mEnergy = 0
        super().__init__()
    
    def readBinary(self, data: bytes):
        self.RoleIndex = self.readInt64(data)
        self.mName = self.read_utf_bytes(data, 32)
        self.mLevel = self.redBase(data, "<i")
        self.mJob = self.redBase(data, "<i")
        self.mGender = self.redBase(data, "<i")
        self.mOnline = self.redBase(data, "<i")
        self.mRid = self.redBase(data, "<i")
        self.bSelected = self.redBase(data, "<B")
        self.bDeleted = self.redBase(data, "<B")
        self.bJinYong = self.redBase(data, "<B")
        self.RoleIndexString = self.read_utf_bytes(data, 16)
        self.createTime = self.redBase(data, "<i")
        self.mAge = self.redBase(data, "<i")
        self.mEnergy = self.redBase(data, "<i")
        return data
    
    def writeBinary(self):
        data = super().writeInt64(self.RoleIndex)
        data += super().write_utf_bytes(self.mName, 32)
        data += struct.pack('<i', self.mLevel)
        data += struct.pack('<i', self.mJob)
        data += struct.pack('<i', self.mGender)
        data += struct.pack('<i', self.mOnline)
        data += struct.pack('<i', self.mRid)
        data += struct.pack('<B', self.bSelected)
        data += struct.pack('<B', self.bDeleted)
        data += struct.pack('<B', self.bJinYong)
        data += super().write_utf_bytes(self.RoleIndexString, 16)
        data += struct.pack('<i', self.createTime)
        data += struct.pack('<i', self.mAge)
        data += struct.pack('<i', self.mEnergy)

        return data
    
# 请求随机名字
class CsgGetRandName(MsgHeader):
    def __init__(self):
        self.Sex = 0
        super().__init__()
    
    def writeBinary(self):
        data = super().writeBinary()
        data += struct.pack('<i', self.Sex)
        return data
    
# 随机名字返回
class MsgGetRandName(MsgHeader):
    def __init__(self):
        self.RandName = ""

        super().__init__()
    
    def readBinary(self, data: bytes):
        super().readBinary(data)
        self.RandName = self.read_utf_bytes(data, 32)
        return data
    
# 创建角色
class CsgCreateRole(MsgHeader):
    def __init__(self):
        super().__init__()
        self.newRole = NetChar()
        self.sType = 32001
    
    def writeBinary(self):
        data = super().writeBinary()
        data += self.newRole.writeBinary()
        return data

#  前端准备好了
class CsgFinishLoadGameMain(MsgHeader):
    def __init__(self):
        super().__init__()
        self.sType = 32702
        self.RoleIndex = "0_0"
    
    def writeBinary(self):
        data = super().writeBinary()
        data += super().writeInt64(self.RoleIndex)
        return data
    
# 进入游戏
class CsgEnterWorld(MsgHeader):
    def __init__(self):
        super().__init__()

        self.sType = 32002
        self.RoleIndex = "0_0"
    
    def writeBinary(self):
        data = super().writeBinary()
        data += super().writeInt64(self.RoleIndex)
        #test
        # data += struct.pack('<i', 0)
        # data += struct.pack('<i', 0)
        return data

# 心跳包 发送
class CsgPing(MsgHeader):
    def __init__(self):
        self.LastPingTime = 0
        super().__init__()
    
    def writeBinary(self):
        data = super().writeBinary()
        data += struct.pack('<q', self.LastPingTime)
        return data
    
# 心跳包 返回
class MsgPing(MsgHeader):
    def __init__(self):
        self.LastPingTime = 0

        super().__init__()
    
    def readBinary(self, data: bytes):
        super().readBinary(data)
        self.LastPingTime = self.redBase(data, "<q")
        return data

# 尝试进入地图 返回
class MsgTryEnterMap(MsgHeader):
    def __init__(self):
        super().__init__()

        self.MapIndex = 0
        self.MapId = "" #32长度
        self.posx = 0
        self.posy = 0
        self.Dir = 0 
        self.IsFirstEnter = 0 #byte
        self.EnityId = 0
        self.BTMode = 0 #bool
        self.IsGhMode = 0 #bool
        self.IsTsMode = 0 #bool
        self.IsTestMode = 0 #bool
        self.sType = 32754
    
    def readBinary(self, data: bytes):
        super().readBinary(data)
        self.MapIndex = self.redBase(data, "<i")
        self.MapId = self.read_utf_bytes(data, 32)
        self.posx = self.redBase(data, "<b")
        self.posy = self.redBase(data, "<b")
        self.Dir = self.redBase(data, "<i")
        self.IsFirstEnter = self.redBase(data, "<B")
        self.EnityId = self.redBase(data, "<i")
        self.BTMode = self.redBase(data, "<B")
        self.IsGhMode = self.redBase(data, "<B")
        self.IsTsMode = self.redBase(data, "<B")
        self.IsTestMode = self.redBase(data, "<B")
        return data
    
# 前端加载地图完成 
class CsgFinishLoadMap(MsgHeader):
    def __init__(self):
        super().__init__()
        self.MapIndex = 0
        self.MapId = "" #32长度
        self.sType = 32701
    
    def writeBinary(self):
        data = super().writeBinary()
        data += struct.pack('<i', self.MapIndex)
        data += super().write_utf_bytes(self.MapId, 32)
        return data

#  进入游戏主场景
class CsgEnterGameMain(MsgHeader):
    def __init__(self):
        super().__init__()
        self.sType = 32711
    
    def writeBinary(self):
        data = super().writeBinary()
        return data
    
#  
class CMgSignOpen(MsgHeader):
    def __init__(self):
        super().__init__()
        self.pingTai = 0
        self.sType = 36221
    
    def writeBinary(self):
        data = super().writeBinary()
        data += struct.pack('<i', self.pingTai)
        return data
    
class CsgMoveHero(MsgHeader):
    def __init__(self):
        super().__init__()
        self.posx = 0
        self.posy = 0
        self.dir = 0

        self.Time = 0
        self.MoveType = 0
        self.Id = 0
        self.MapId = "xsc" #32长度
        self.sType = 32601
    
    def writeBinary(self):
        data = super().writeBinary()
        data += struct.pack('<h', self.posx)
        data += struct.pack('<h', self.posy)
        data += struct.pack('<b', self.dir)

        data += struct.pack('<q', self.Time)
        data += struct.pack('<B', self.MoveType)
        data += struct.pack('<i', self.Id)
        data += super().write_utf_bytes(self.MapId, 32)
        
        return data